package cn.jn.lhm.netty.part08.chat.protocol;

import cn.jn.lhm.netty.part08.chat.config.Config;
import cn.jn.lhm.netty.part08.chat.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author lhm 2753914576@qq.com
 * @time 2023/10/31 - 22:38
 **/
@Slf4j
public class ScopeMessageCodec extends MessageToMessageCodec<ByteBuf, Message> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        ByteBuf out = ctx.alloc().buffer();
        // 1. 4个字节的魔数
        out.writeBytes(new byte[]{1, 2, 3, 4});
        // 2. 1个字节的版本号
        out.writeByte(1);
        // 3. 1个字节的序列化算法 0:jdk 1:json
        out.writeByte(Config.getSerializerAlgorithm().ordinal());
        // 4. 1个字节的指令类型
        out.writeByte(msg.getMessageType());
        // 5. 4个字节的消息序号
        out.writeInt(msg.getSequenceId());
        // 6. 1个字节的对齐填充
        out.writeByte(0xff);
        // 7. 4个字节的请求长度
        byte[] bytes = Config.getSerializerAlgorithm().serialize(msg);

        out.writeInt(bytes.length);

        // 8. 消息正文
        out.writeBytes(bytes);
        outList.add(out);
    }

    private boolean readOver = true;

    private int len;

    private byte serializerType;

    private byte messageType;

    private byte[] completeBytes = new byte[0];

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (readOver) {
            // 读取4个字节的整数作为magicNum
            int magicNum = in.readInt();
            // 读取1个字节的字节版本号
            byte version = in.readByte();
            // 读取1个字节的序列化类型
            serializerType = in.readByte();
            // 读取1个字节的消息类型
            messageType = in.readByte();
            // 读取4个字节的整数作为messageId
            int messageId = in.readInt();
            // 读取1个字节无用数据
            in.readByte();
            // 读取4个字节的长度len
            len = in.readInt();
        }
        readOver = len <= in.readableBytes();
        int readLength = readOver ? len : in.readableBytes();
        len -= in.readableBytes();
        // 创建长度为len的字节数组
        byte[] bytes = new byte[readLength];
        // 从输入流中读取len个字节到bytes数组中
        in.readBytes(bytes, 0, in.readableBytes());

        // 将读取的字节数组添加到completeBytes数组中
        completeBytes = mergeByteArrays(completeBytes, bytes);

        if (readOver) {
            Class<? extends Message> messageClass = Message.getMessageClass(messageType);
            Message message = Serializer.Algorithm.values()[serializerType].deserialize(messageClass, completeBytes);
            out.add(message);
            completeBytes = new byte[0];
        }
    }

    public static byte[] mergeByteArrays(byte[] a, byte[] b) {
        byte[] result = new byte[a.length + b.length];
        System.arraycopy(a, 0, result, 0, a.length);
        System.arraycopy(b, 0, result, a.length, b.length);
        return result;
    }
}
